package cc.verywell.pureblock.msg.nfs.linkmap;

import java.nio.BufferOverflowException;
import java.nio.ByteBuffer;
import java.util.Arrays;

/**
* 
* length+第一个key
* 和上一个相同的位数+不同的位数+不同的key;
* 和上一个相同的位数+不同的位数+不同的key;
* 
* Copyright © 2019 TanYaqiu. All rights reserved.
* @author TanYaqiu 
* @address flat 601
* @date 2019年6月16日 下午3:36:05
*/
public class EasyTableHDpage implements EasyTable {

	final byte[] page;
	public EasyTableHDpage(byte[] page) {
		this.page = page;
	}

	@Override
	public EasyIterator get(LinkCell startWith) {
		int matchTarget = startWith.encoded.length;
		ByteBuffer bb = ByteBuffer.wrap(page);
		int b,e = LinkCell.lengthDecodeInt(bb);
		byte[] current = new byte[e];
		bb.get(current);
		int l = current.length;
		int match = LinkCell.smallerAndStartWith(current, l-8, startWith, 0);
		if(match<0)return null;
		while(match!=matchTarget) {
			if(!bb.hasRemaining())return null;
			b = LinkCell.lengthDecodeInt(bb);
			e = LinkCell.lengthDecodeInt(bb);
			l = b+e;
			if(current.length<l) {
				int i = current.length;
				while(i>0 && i<l)i<<=1;
				if(i<=0)i = l;
				byte[] nw = new byte[i];
				System.arraycopy(current, 0, nw, 0, b);
				current = nw;
			}
			bb.get(current, b, e);
			if(b<match)match = b;
			match = LinkCell.smallerAndStartWith(current, l-8, startWith, match);
			if(match<0)return null;
		}
		if(current.length!=l) {
			current = Arrays.copyOf(current, l);
		}
		LinkCell cr = new LinkCell(current);
		return new PageIterator(bb,cr,startWith);
	}
	
	/**
	 * 这里可能会出现多个版本;
	 * <p>PageIterator </p>
	 * @author TanYaqiu 
	 * Copyright © 2019 TanYaqiu. All rights reserved.
	 */
	static private class PageIterator implements EasyIterator{
		protected ByteBuffer bb;
		protected LinkCell startWith;
		protected LinkCell current;
		public PageIterator(ByteBuffer bb,LinkCell current,LinkCell startWith) {
			this.bb = bb;
			this.startWith = startWith;
			this.current = current;
		}

		@Override
		public boolean hasNext() {
			return current!=null;
		}

		@Override
		public LinkCell next() {
			LinkCell cr = current;
			current = null;
			if(bb.hasRemaining()) {
				int b = LinkCell.lengthDecodeInt(bb);
				int e = LinkCell.lengthDecodeInt(bb);
				int l = b+e;
				byte[] nxt = new byte[l];
				System.arraycopy(cr.encoded, 0, nxt, 0, b);
				bb.get(nxt, b, e);
				int matchTarget = startWith.encoded.length;
				if(b>matchTarget || matchTarget==LinkCell.startWith(nxt, l, startWith, b)) {
					current = new LinkCell(nxt);
				}
			}
			return cr;
		}

		@Override
		public LinkCell current() {
			return current;
		}
	}
	
	////写入add
	static public LinkCell add(ByteBuffer bb,EasyIterator it) {
		LinkCell cr = it.current();
		LinkCell.lengthEncodeInt(bb, cr.encoded.length);
		bb.put(cr.encoded);
		it.next();
		while(it.hasNext()) {
			LinkCell nxt = it.current();
			try {
				bb.mark();
				byte[] m = nxt.encoded;
				int match = LinkCell.startWith(m,m.length,cr,0);
				LinkCell.lengthEncodeInt(bb, match);
				int rest = m.length-match;
				LinkCell.lengthEncodeInt(bb, rest);
				if(rest>0)bb.put(m, match, rest);
			}catch(BufferOverflowException b) {
				bb.reset();
				return cr;
			}
			cr = nxt;
			it.next();
		}
		return cr;
	}
}
